[鐵人碎念Time]
我也擠了擠我的乳溝,發現時間還是只剩一小時啊!
妳呢?快擠看看!!
我可以不要百煉成鋼,可以成神嗎
==========
誒~老闆不對啊!(林宇)
老闆很對啊,哪裡不對了~除了現在還是魯蛇外,一切都很對啊
不是啦,是你介紹QR Code、Barcode產生器,那怎沒連掃描內容的APP也順便介紹啊!!(林宇)
因那時蕭亦翔沒教我也沒提到啊,再說現在掃瞄器這麼多,Line也有,且iOS 11在相機中內建了掃描QR Code的功能了啊!
不管啦,我就是好奇嗎~教我啦!(林宇撒嬌樣)
先說好,這可比前面說的那兩樣難多了,同時也複雜多了唷...
(林宇一臉可憐樣盯著看)
唉~
好啦好啦,就算我同場加映教妳吧
就知道你人最好了!!(林宇)
==========
Step1. 首先,先到「Apple Developer」(https://developer.apple.com/)申請開發者帳號
(這之前要先有Apple ID(https://appleid.apple.com/account#!&page=create))
關於怎申請,這方面我就不多做說明了,Google上可以查到許多
Step2. 接著在Xcode左上選單「Xcode」->「Preferences...」
Step3.點選「Accounts」->請照著圖片上的步驟1「+」->接著步驟2選擇「Apple ID」->點選步驟三3「Continue」->登入Apple ID
Step4. 登入後,請按照圖上所示點選步驟1管理憑證「Manage Certificates...」->點選步驟2「+」->步驟3加入「iOS Developmengt」->「Done」
(以上為等等要順利編譯後在手機上呈現的步驟之一)
==========
Step5. 接著建立新專案,名稱為「scanBarcode」,Team應該可以選擇,不會只有「None」的選項
Step6. 在畫面上拉出一個View跟一個Label
Step7. 導入AVFoundation框架
import AVFoundation //導入AVFoundation框架
Step8. class後方加入AVCaptureMetadataOutputObjectsDelegate協定
class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
Step9. 接著宣告兩個等等會用到的常數,元件連結View命名為「CameraView」,Label命名為「ContentValue」
// 協調從接收裝置到輸出元件間的資料動作
let AVCsession = AVCaptureSession()
// 即時顯示預覽目前相機接收到的畫面
let AVCVideoPreviewLayer = AVCaptureVideoPreviewLayer()
@IBOutlet weak var CameraView: UIView!
@IBOutlet weak var ContentValue: UILabel!
Step10. 接著在viewDidLoad內加入以下Code,內已有註解請觀看理解
//啟動相機
AVCsession.startRunning()
// 取得預設的相機裝置(後鏡頭)
let AVCdevice = AVCaptureDevice.default(for: .video)
do {
// 設定資料來源為後鏡頭
let videoInput = try AVCaptureDeviceInput(device: AVCdevice!)
AVCsession.addInput(videoInput)
// 設定所取得資料為MetaData物件資料
let AVCvideoOutput = AVCaptureMetadataOutput()
AVCsession.addOutput(AVCvideoOutput)
// 接收所有MetaData資料
AVCvideoOutput.metadataObjectTypes = AVCvideoOutput.availableMetadataObjectTypes
AVCvideoOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
// 設定瀏覽畫面
AVCVideoPreviewLayer.session = AVCsession
AVCVideoPreviewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
CameraView.layer.addSublayer(AVCVideoPreviewLayer)
} catch {
// 拋出錯誤訊息
print(error)
}
Step11. 用於Function通知控制器將要佈局view的子控制元件時使用
/*
Function通知控制器將要佈局view的子控制元件時使用
每當畫面的bounds改變,view將調整其子控制元件位置
在控制器生命週期中,該方法可能會被多次使用
*/
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
AVCVideoPreviewLayer.frame = CameraView.bounds
}
Step12. 加入輸出訊息的方法
func metadataOutput(_ captureOutput: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
for metaData in metadataObjects {
if let data = metaData as? AVMetadataMachineReadableCodeObject {
// 條碼內容
ContentValue.text = data.stringValue
} else {
print("error")
}
}
}
Step13. 將模擬器類型挑選到自己的手機名稱(手機要先連接好)後執行->會出現取得權限畫面(這邊如出現問題,請先看下方解決方法)->掃描確認訊息->Finish
==========
各位在執行時,有無出現錯誤訊息呢?
就類似下方圖示(或者閃退):
那是因為我們少說到一個地方,條用相機功能權限解,解決方法:
Step1. 開啟info.plist文件
Step2. 加入相機權限代碼
可參考此資源:https://www.jianshu.com/p/eb9af5982bc0
==========
完整內碼提供:
import UIKit
import AVFoundation //導入AVFoundation框架
/*
(可查詢UIViewController生命週期)
(可查詢AVCaptureMetadataOutputObjectsDelegate協定)
*/
class ViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
// 協調從接收裝置到輸出元件間的資料動作
let AVCsession = AVCaptureSession()
// 即時顯示預覽目前相機接收到的畫面
let AVCVideoPreviewLayer = AVCaptureVideoPreviewLayer()
@IBOutlet weak var CameraView: UIView!
@IBOutlet weak var ContentValue: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
//啟動相機
AVCsession.startRunning()
// 取得預設的相機裝置(後鏡頭)
let AVCdevice = AVCaptureDevice.default(for: .video)
do {
// 設定資料來源為後鏡頭
let videoInput = try AVCaptureDeviceInput(device: AVCdevice!)
AVCsession.addInput(videoInput)
// 設定所取得資料為MetaData物件資料
let AVCvideoOutput = AVCaptureMetadataOutput()
AVCsession.addOutput(AVCvideoOutput)
// 接收所有MetaData資料
AVCvideoOutput.metadataObjectTypes = AVCvideoOutput.availableMetadataObjectTypes
AVCvideoOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
// 設定瀏覽畫面
AVCVideoPreviewLayer.session = AVCsession
AVCVideoPreviewLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
CameraView.layer.addSublayer(AVCVideoPreviewLayer)
} catch {
// 拋出錯誤訊息
print(error)
}
}
/*
Function通知控制器將要佈局view的子控制元件時使用
每當畫面的bounds改變,view將調整其子控制元件位置
在控制器生命週期中,該方法可能會被多次使用
*/
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
AVCVideoPreviewLayer.frame = CameraView.bounds
}
func metadataOutput(_ captureOutput: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
for metaData in metadataObjects {
if let data = metaData as? AVMetadataMachineReadableCodeObject {
// 條碼內容
ContentValue.text = data.stringValue
} else {
print("error")
}
}
}
}